/// <reference path = "./ShaderComponent.ts" />

module lcc$render {

const {ccclass, property, menu } = cc._decorator;

//@ts-ignore
let gfx = cc.gfx;

enum ShapeType {
	/**
	 * 节点尺寸
	 */
	NODE = 0,

	/**
	 * 自定义尺寸
	 */
	CUSTOM,
}

enum SizeMode {
	/**
	 * 自定义尺寸
	 */
	CUSTOM = 0,

	/**
	 * 自动适配为精灵裁剪后的尺寸
	 */
	TRIMMED,

	/**
	 * 自动适配为精灵原图尺寸
	 */
	RAW,
}

@ccclass("lcc$render.ShaderSpriteFrame")
@menu("i18n:lcc-render.menu_component/ShaderSpriteFrame")
export class ShaderSpriteFrame extends ShaderComponent {

	_tag:string = "spriteframe";

	@property(VariableConfig)
	_textureVar:VariableConfig = new VariableConfig(
		false, VariableType.UNIFORM, 
		"", false, "", "USE_TEXTURE", false, "texture");
	@property({
		type : VariableConfig,
		tooltip : "纹理变量"
	})
	get textureVar(){
		return this._textureVar;
	}
	set textureVar(value:VariableConfig){
		this._textureVar = value;
		this.onRenderUpdateMaterial();
	}
	
	@property({
		type: cc.SpriteAtlas,
		tooltip: CC_DEV && 'i18n:COMPONENT.sprite.atlas',
		editorOnly: true,
		visible: true,
		animatable: false
	})
	_atlas: cc.SpriteAtlas = null;

    @property(cc.SpriteFrame)
	_spriteFrame:cc.SpriteFrame = null;
	@property({
		type : cc.SpriteFrame,
		tooltip : "精灵帧对象"
	})
	get spriteFrame(){
		return this._spriteFrame;
	}
	set spriteFrame(value:cc.SpriteFrame){
		if(this._spriteFrame !== value){
			let lastSprite = this._spriteFrame;
			if (CC_EDITOR) {
				// @ts-ignore
				if (((lastSprite && lastSprite._uuid) === (value && value._uuid))) {
					return;
				}
			}
			else {
				if (lastSprite === value) {
					return;
				}
			}
			this._spriteFrame = value;
			this._useSpriteFrame(lastSprite);
			if (CC_EDITOR) {
				this.node.emit('spriteframe-changed', this);
			}
		}
	}

    @property()
    _useShape:boolean = false;
	@property({
		tooltip:"使用形状"
	})
	get useShape(){
		return this._useShape;
	}
	set useShape(value:boolean){
		if(this._useShape !== value){
			this._useShape = value;
			if(value){
				this.node.emit("shader_useshape", this);
			}
			this.node.emit("shader_update_shape");
            this._useSpriteSize();
		}
	}
	
    @property({
		type : cc.Enum(ShapeType)
	})
    _shapeType:ShapeType = ShapeType.NODE;
	@property({
		type : cc.Enum(ShapeType),
		tooltip:"形状类型",
		visible () {
			return this._useShape;
		},
	})
	get shapeType(){
		return this._shapeType;
	}
	set shapeType(value:ShapeType){
		if(this._shapeType !== value){
			this._shapeType = value;
			this.node.emit("shader_update_vertex");
		}
	}

	@property(cc.Size)
	_size:cc.Size = cc.size(0,0);
	@property({
		type:cc.Size,
		tooltip : "形状的尺寸",
		visible () {
			return this._useShape && this._shapeType == ShapeType.CUSTOM;
		}
	})
	get size(){
		return this._size;
	}
	set size(value:cc.Size){
		this._size = value;
		this._sizeMode = SizeMode.CUSTOM;
		this.node.emit("shader_update_vertex");
		if(this._syncSizeToNode){
			this.node.setContentSize(this._size);
		}
	}
	
	@property(cc.Vec2)
	_anchor:cc.Vec2 = cc.v2(0.5, 0.5);
	@property({
		type:cc.Vec2,
		tooltip : "形状的锚点",
		visible () {
			return this._useShape && this._shapeType == ShapeType.CUSTOM;
		},
	})
	get anchor(){
		return this._anchor;
	}
	set anchor(value:cc.Vec2){
		this._anchor = value;
		this.node.emit("shader_update_vertex");
		if(this._syncSizeToNode){
			this.node.setAnchorPoint(this._anchor);
		}
	}
	
    @property()
    _syncSizeToNode:boolean = true;
	@property({
		tooltip:"同步尺寸到节点",
		visible () {
			return this._useShape && this._shapeType == ShapeType.CUSTOM;
		},
	})
	get syncSizeToNode(){
		return this._syncSizeToNode;
	}
	set syncSizeToNode(value:boolean){
		if(this._syncSizeToNode !== value){
			this._syncSizeToNode = value;
			this.node.setContentSize(this._size);
			this.node.setAnchorPoint(this._anchor);
		}
	}
	
    @property({
        type : cc.Enum(SizeMode)
    })
	_sizeMode:SizeMode = SizeMode.TRIMMED;
	@property({
		type : cc.Enum(SizeMode),
		visible () {
			return this._useShape && this._shapeType == ShapeType.CUSTOM;
		},
		animatable: false,
		tooltip: CC_DEV && 'i18n:COMPONENT.sprite.size_mode'
	})
	get sizeMode(){
		return this._sizeMode;
	}
	set sizeMode(value:SizeMode){
		if(this._sizeMode !== value){
			this._sizeMode = value;
			this._useSpriteSize();
		}
	}

    @property()
	_isTrimmedMode:boolean = true;
	@property({
		visible () {
			return this._useShape;
		},
		animatable: false,
		tooltip: CC_DEV && 'i18n:COMPONENT.sprite.trim',
	})
	get trim(){
		return this._isTrimmedMode;
	}
	set trim(value:boolean){
		if(this._isTrimmedMode !== value){
			this._isTrimmedMode = value;
			this.node.emit("shader_update_vertex");
		}
    }
    
    @property()
    _useUV:boolean = false;
	@property({
		tooltip:"使用 UV"
	})
	get useUV(){
		return this._useUV;
	}
	set useUV(value:boolean){
		if(this._useUV !== value){
			this._useUV = value;
			this.checkUVIndexes();
			this.node.emit("shader_update_attribute");
		}
	}
	
	@property(VariableConfig)
	_uvVar:VariableConfig = new VariableConfig(
		false, VariableType.ATTRIBUTE, 
		"USE_TEXTURE", true, "a_uv0", "", false, "");
	@property({
		type : VariableConfig,
		tooltip : "UV变量",
		visible (){
			return this._useUV;
		},
	})
	get uvVar(){
		return this._uvVar;
	}
	set uvVar(value:VariableConfig){
		this._uvVar = value;
		this.node.emit("shader_update_attribute");
	}
	
    @property()
    _customUV:boolean = false;
	@property({
		tooltip:"自定义 UV",
		visible (){
			return this._useUV;
		},
	})
	get customUV(){
		return this._customUV;
	}
	set customUV(value:boolean){
		if(this._customUV !== value){
			this._customUV = value;
			this.checkUVIndexes();
			this.onRenderUpdateMaterial();
			this.node.emit("shader_update_attribute");
		}
	}
	
	@property([cc.Integer])
	_uvIndexes:number[] = [];
	@property({
		type : [cc.Integer],
		tooltip : "UV索引表",
		visible (){
			return this._useUV && this._customUV;
		},
	})
	get uvIndexes(){
		return this._uvIndexes;
	}
	set uvIndexes(value:number[]){
		this._uvIndexes = value;
		this.checkUVIndexes();
		this.node.emit("shader_update_vertex");
	}

    @property()
    _useUVRect:boolean = false;
	@property({
		tooltip:"使用UV区域(合图后的区域)"
	})
	get useUVRect(){
		return this._useUVRect;
	}
	set useUVRect(value:boolean){
		if(this._useUVRect !== value){
			this._useUVRect = value;
			this.onRenderUpdateMaterial();
			this.node.emit("shader_update_attribute");
		}
	}
	
	@property(VariableConfig)
	_uvRectVar:VariableConfig = new VariableConfig(
		true, VariableType.UNIFORM, 
		"ATTR_UVRECT", false, "a_uvrect", "UNIF_UVRECT", false, "u_uvrect");
	@property({
		type : VariableConfig,
		tooltip : "UV区域变量",
		visible (){
			return this._useUVRect;
		},
	})
	get uvRectVar(){
		return this._uvRectVar;
	}
	set uvRectVar(value:VariableConfig){
		this._uvRectVar = value;
		this.onRenderUpdateMaterial();
		this.node.emit("shader_update_attribute");
	}
	
    @property()
    _useFrameSize:boolean = false;
	@property({
		tooltip:"使用帧尺寸(像素大小)"
	})
	get useFrameSize(){
		return this._useFrameSize;
	}
	set useFrameSize(value:boolean){
		if(this._useFrameSize !== value){
			this._useFrameSize = value;
			this.onRenderUpdateMaterial();
			this.node.emit("shader_update_attribute");
		}
	}
	
	@property(VariableConfig)
	_frameSizeVar:VariableConfig = new VariableConfig(
		true, VariableType.UNIFORM, 
		"ATTR_FRAMESIZE", false, "a_framesize", "UNIF_FRAMESIZE", false, "u_framesize");
	@property({
		type : VariableConfig,
		tooltip : "帧尺寸变量",
		visible (){
			return this._useFrameSize;
		},
	})
	get frameSizeVar(){
		return this._frameSizeVar;
	}
	set frameSizeVar(value:VariableConfig){
		this._frameSizeVar = value;
		this.onRenderUpdateMaterial();
		this.node.emit("shader_update_attribute");
	}
	
	/**
	 * 形状矩形区域
	 */
	_shapeRect: number[] = null;
	
	/**
	 * uv偏移
	 */
    private _uvOffest:number = 0;

	/**
	 * uv矩形偏移
	 */
    private _uvrOffset:number = 0;

	/**
	 * 帧尺寸偏移
	 */
    private _fsOffset:number = 0;

    onLoad(){
        this._spriteFrame && this._spriteFrame.ensureLoadTexture();
        this.node.on("shader_useshape", this.onShaderuseShape, this);
        this.node.on("render_check_shape", this.onRenderCheckShape, this);
        this.node.on("render_shape_checked", this.checkUVIndexes, this);
        this.node.on("render_prepare", this.onRenderPrepare, this);
        this.node.on("render_update_material", this.onRenderUpdateMaterial, this);
		this.node.on("render_update_attribute", this.onRenderUpdateAttribute, this);
		this.node.on("render_update_shape", this.onRenderUpdateShape, this);
		this.node.on("render_update_vertex", this.onRenderUpdateRenderData, this);
		this.node.on("render_update_worldvertex", this.updateWorldVerts, this);
		this.node.on("render_validate_render", this.onRenderValidateRender, this);
    }

    onDestroy(){
        this.node.targetOff(this);
    }
    
	onEnable(){
        this.onStateUpdate(true);
	}

	onDisable(){
        this.onStateUpdate(false);
    }

    private onStateUpdate(enable:boolean){
		this.node.emit("shader_update_tag");
		this.onRenderUpdateMaterial();
		this.node.emit("shader_update_attribute");
		if(enable){
			this._useSpriteFrame(null);
		}
		this.checkUVIndexes();
		//this.node.emit("shader_update_vertex");
	}
	
	/**
	 * 检查UV索引
	 */
	private checkUVIndexes(){
		if(this.enabled){
			if(this._useUV){
				if(this._customUV){
					let rcomp = this.getComponent(RenderSystem);
					if(rcomp){
						let uvi = this._uvIndexes;
						let vc = rcomp._verticesCount;
						for(let i = 0; i < vc; i++){
							let idx = uvi[i];
							if(idx == null){
								uvi[i] = i % 4;
							}else if(idx > 3){
								uvi[i] = 3;
							}else if(idx < 0){
								uvi[i] = 0;
							}
						}
						if(uvi.length > vc){
							this._uvIndexes = uvi.slice(0, vc);
						}
					}
				}else{
					this._uvIndexes = [];
				}
			}else{
				this._uvIndexes = [];
			}
		}
	}
    
	private onShaderuseShape(comp:cc.Component){
		if(this.enabled && this !== comp){
			this._useShape = false;
		}
	}

	private onRenderCheckShape(comp:RenderSystem){
		if(this.enabled && this._useShape){
			comp.setShaderShape(4, 6);
		}
	}

	private onRenderPrepare(comp:RenderSystem){
		if(this.enabled){
			// 打包动态纹理
			this.packToDynamicAtlas(comp, this._spriteFrame);
		}
	}
	
	private getUVRect(comp:RenderSystem){
		let rect = new cc.Vec4();
		if(this._spriteFrame){
			// @ts-ignore
			let uv = this._spriteFrame.uv;
			let l = uv[0];
			let b = uv[1];
			let w = uv[6] - l;
			let h = uv[7] - b;
			rect.x = l;
			rect.y = b;
			rect.z = w;
			rect.w = h;
		}
		return rect;
	}
	
    private onRenderUpdateMaterial (comp:RenderSystem = this.getComponent(RenderSystem)) {
		if(comp){
			let texture = this._spriteFrame && this._spriteFrame.getTexture();
			// make sure material is belong to self.
			//@ts-ignore
			let material = comp._materials[0];
			if (material) {
				if (this.checkMaterialMacro(material, this._textureVar.unifMacro)) {
					if(this.enabled){
						this.defineMaterialMacro(material, this._textureVar.unifMacro, true);
						material.setProperty(this._textureVar.unifName, texture);
					}else{
						this.defineMaterialMacro(material, this._textureVar.unifMacro, false);
					}
				}
				if (this.checkMaterialMacro(material, this._uvRectVar.unifMacro)) {
					if(this.enabled && this._useUVRect && this._uvRectVar.type === VariableType.UNIFORM){
						this.defineMaterialMacro(material, this._uvRectVar.unifMacro, true);
						material.setProperty(this._uvRectVar.unifName, this.getUVRect(comp));
						//Editor.log("onRenderUpdateMaterial", this.getUVRect(comp));
					}else{
						this.defineMaterialMacro(material, this._uvRectVar.unifMacro, false);
					}
				}
				if (this.checkMaterialMacro(material, this._frameSizeVar.unifMacro)) {
					if(this.enabled &&this._useFrameSize && this._frameSizeVar.type === VariableType.UNIFORM){
						this.defineMaterialMacro(material, this._frameSizeVar.unifMacro, true);
						if(this._spriteFrame){
							//@ts-ignore
							let rect = this._spriteFrame._rect;
							material.setProperty(this._frameSizeVar.unifName, cc.v2(rect.width, rect.height));
						}else {
							material.setProperty(this._frameSizeVar.unifName, cc.v2(1, 1));
						}
						//Editor.log("onRenderUpdateMaterial", this.getUVRect(comp));
					}else{
						this.defineMaterialMacro(material, this._frameSizeVar.unifMacro, false);
					}
				}
			}
		}
	}
	
	private onRenderUpdateAttribute(comp:RenderSystem = this.getComponent(RenderSystem)){
		if(comp){
			// @ts-ignore
			let material = comp._materials[0];
			if (material) {
				if (this.checkMaterialMacro(material, this._uvVar.attrMacro)) {
					if(this.enabled && this._useUV){
						this.defineMaterialMacro(material, this._uvVar.attrMacro, true);
						this._uvOffest = comp.addVertexAttribute({ 
							name: this._uvVar.attrName, 
							type: gfx.ATTR_TYPE_FLOAT32, 
							num: 2 
						}, 2);
						//Editor.log("onRenderUpdateAttribute", this._uvrOffset);
					}else{
						this.defineMaterialMacro(material, this._uvVar.attrMacro, false);
						this._uvOffest = 0;
					}
				}
				if (this.checkMaterialMacro(material, this._uvRectVar.attrMacro)) {
					if(this.enabled && this._useUVRect && this._uvRectVar.type === VariableType.ATTRIBUTE){
						this.defineMaterialMacro(material, this._uvRectVar.attrMacro, true);
						this._uvrOffset = comp.addVertexAttribute({ 
							name: this._uvRectVar.attrName, 
							type: gfx.ATTR_TYPE_FLOAT32, 
							num: 4 
						}, 4);
						//Editor.log("onRenderUpdateAttribute", this._uvrOffset);
					}else{
						this.defineMaterialMacro(material, this._uvRectVar.attrMacro, false);
						this._uvrOffset = 0;
					}
				}
				if (this.checkMaterialMacro(material, this._frameSizeVar.attrMacro)) {
					if(this.enabled && this._useFrameSize && this._frameSizeVar.type === VariableType.ATTRIBUTE){
						this.defineMaterialMacro(material, this._frameSizeVar.attrMacro, true);
						this._fsOffset = comp.addVertexAttribute({ 
							name: this._frameSizeVar.attrName, 
							type: gfx.ATTR_TYPE_FLOAT32, 
							num: 2 
						}, 2);
						//Editor.log("onRenderUpdateAttribute", this._uvrOffset);
					}else{
						this.defineMaterialMacro(material, this._frameSizeVar.attrMacro, false);
						this._fsOffset = 0;
					}
				}
			}
		}
	}

	private onRenderUpdateShape(comp:RenderSystem = this.getComponent(RenderSystem)){
		if(this.enabled && this._useShape){
			// @ts-ignore
			let rdata = comp._assembler.renderData;

			rdata.initQuadIndices(rdata.iDatas[0]);

			this._shapeRect = [ 0, 0, 0, 0 ];
		}else{
			this._shapeRect = null;
		}
	}
	
	private onRenderUpdateRenderData(comp:RenderSystem = this.getComponent(RenderSystem)){
        if(comp && this.enabled){
			//Editor.log("onRenderUpdateVertex");
			// @ts-ignore
			let assembler = comp._assembler;

			// 更新顶点
			if(this._useShape){
				// @ts-ignore
				let cw, ch, appx, appy, l, b, r, t;
				if(this._shapeType == ShapeType.NODE){
					let node = this.node;
					cw = node.width;
					ch = node.height;
					appx = node.anchorX * cw;
					appy = node.anchorY * ch;
				}else{
					cw = this._size.width;
					ch = this._size.height;
					appx = this._anchor.x * cw;
					appy = this._anchor.y * ch;
				}
				if (this.trim) {
					l = -appx;
					b = -appy;
					r = cw - appx;
					t = ch - appy;
				}
				else {
					let frame = this._spriteFrame,
						//@ts-ignore
						ow = frame._originalSize.width, oh = frame._originalSize.height,
						//@ts-ignore
						rw = frame._rect.width, rh = frame._rect.height,
						//@ts-ignore
						offset = frame._offset,
						scaleX = cw / ow, scaleY = ch / oh;
					let trimLeft = offset.x + (ow - rw) / 2;
					let trimRight = offset.x - (ow - rw) / 2;
					let trimBottom = offset.y + (oh - rh) / 2;
					let trimTop = offset.y - (oh - rh) / 2;
					l = trimLeft * scaleX - appx;
					b = trimBottom * scaleY - appy;
					r = cw + trimRight * scaleX - appx;
					t = ch + trimTop * scaleY - appy;
				}
	
				let local = this._shapeRect;
				local[0] = l;
				local[1] = b;
				local[2] = r;
				local[3] = t;

				this.updateWorldVerts(comp);
			}

			// 使用UV
			if(this._useUV && this._uvOffest > 0){
				// @ts-ignore
				let uv = this._spriteFrame.uv;
				let cuvi = this._uvIndexes;
				let uvOffset = this._uvOffest;
				let floatsPerVert = assembler.floatsPerVert;
				let verts = assembler.renderData.vDatas[0];
				for (let i = 0; i < 4; i++) {
					let srcOffset = (this._customUV ? cuvi[i] : i) * 2;
					let dstOffset = floatsPerVert * i + uvOffset;
					verts[dstOffset] = uv[srcOffset];
					verts[dstOffset + 1] = uv[srcOffset + 1];
				}
			}

			// 使用UV区域
			if(this._useUVRect && this._uvrOffset > 0){
				let uvr = this.getUVRect(comp);
				if(uvr){
					let uvrOffset = this._uvrOffset;
					let floatsPerVert = assembler.floatsPerVert;
					let verts = assembler.renderData.vDatas[0];
					for (let i = 0; i < 4; i++) {
						let dstOffset = floatsPerVert * i + uvrOffset;
						verts[dstOffset] = uvr.x;
						verts[dstOffset + 1] = uvr.y;
						verts[dstOffset + 2] = uvr.z;
						verts[dstOffset + 3] = uvr.w;
					}
				}
			}

			// 使用帧尺寸大小
			if(this._useFrameSize && this._fsOffset > 0){
				//@ts-ignore
				let rect = this._spriteFrame._rect;
				let fsOffset = this._fsOffset;
				let floatsPerVert = assembler.floatsPerVert;
				let verts = assembler.renderData.vDatas[0];
				for (let i = 0; i < 4; i++) {
					let dstOffset = floatsPerVert * i + fsOffset;
					verts[dstOffset] = rect.width;
					verts[dstOffset + 1] = rect.height;
				}
			}
        }
	}

    updateWorldVerts(comp:RenderSystem) {
		if(this.enabled && this._useShape){
			if (CC_NATIVERENDERER) {
				this.updateWorldVertsNative(comp);
			} else {
				this.updateWorldVertsWebGL(comp);
			}
		}
    }

    updateWorldVertsWebGL(comp:RenderSystem) {
		// @ts-ignore
		let assembler = comp._assembler;
        let local = this._shapeRect;
        let verts = assembler.renderData.vDatas[0];

		//@ts-ignore
        let matrix = comp.node._worldMatrix;
        let matrixm = matrix.m,
            a = matrixm[0], b = matrixm[1], c = matrixm[4], d = matrixm[5],
            tx = matrixm[12], ty = matrixm[13];

        let vl = local[0], vr = local[2],
            vb = local[1], vt = local[3];
        
        /*
        m00 = 1, m01 = 0, m02 = 0, m03 = 0,
        m04 = 0, m05 = 1, m06 = 0, m07 = 0,
        m08 = 0, m09 = 0, m10 = 1, m11 = 0,
        m12 = 0, m13 = 0, m14 = 0, m15 = 1
        */
        let justTranslate = a === 1 && b === 0 && c === 0 && d === 1;

        let index = 0;
        let floatsPerVert = assembler.floatsPerVert;
        if (justTranslate) {
            // left bottom
            verts[index] = vl + tx;
            verts[index+1] = vb + ty;
            index += floatsPerVert;
            // right bottom
            verts[index] = vr + tx;
            verts[index+1] = vb + ty;
            index += floatsPerVert;
            // left top
            verts[index] = vl + tx;
            verts[index+1] = vt + ty;
            index += floatsPerVert;
            // right top
            verts[index] = vr + tx;
            verts[index+1] = vt + ty;
        } else {
            let al = a * vl, ar = a * vr,
            bl = b * vl, br = b * vr,
            cb = c * vb, ct = c * vt,
            db = d * vb, dt = d * vt;

            // left bottom
            // newx = vl * a + vb * c + tx
            // newy = vl * b + vb * d + ty
            verts[index] = al + cb + tx;
            verts[index+1] = bl + db + ty;
            index += floatsPerVert;
            // right bottom
            verts[index] = ar + cb + tx;
            verts[index+1] = br + db + ty;
            index += floatsPerVert;
            // left top
            verts[index] = al + ct + tx;
            verts[index+1] = bl + dt + ty;
            index += floatsPerVert;
            // right top
            verts[index] = ar + ct + tx;
            verts[index+1] = br + dt + ty;
        }
    }

    updateWorldVertsNative(comp:RenderSystem) {
		// @ts-ignore
		let assembler = comp._assembler;
        let local = this._shapeRect;
        let verts = assembler.renderData.vDatas[0];
        let floatsPerVert = assembler.floatsPerVert;
		
        let vl = local[0],
            vr = local[2],
            vb = local[1],
            vt = local[3];
      
        let index: number = 0;
        // left bottom
        verts[index] = vl;
        verts[index+1] = vb;
        index += floatsPerVert;
        // right bottom
        verts[index] = vr;
        verts[index+1] = vb;
        index += floatsPerVert;
        // left top
        verts[index] = vl;
        verts[index+1] = vt;
        index += floatsPerVert;
        // right top
        verts[index] = vr;
        verts[index+1] = vt;
    }

    private onRenderValidateRender (comp:RenderSystem) {
        if(this.enabled){
            let spriteFrame = this._spriteFrame;
            if (spriteFrame &&
                spriteFrame.textureLoaded()) {
                return;
			}
			//@ts-ignore
            comp.disableRender();
        }
    }

    packToDynamicAtlas(comp, frame) {
        if (CC_TEST) return;
        
        if (!frame._original && cc.dynamicAtlasManager && frame._texture.packable) {
            let packedFrame = cc.dynamicAtlasManager.insertSpriteFrame(frame);
            //@ts-ignore
            if (packedFrame) {
                frame._setDynamicAtlasFrame(packedFrame);
            }
        }
        let material = comp._materials[0];
        if (!material) return;
        
        if (material.getProperty(this._textureVar.unifName) !== frame._texture) {
			this.onRenderUpdateMaterial();
			this.node.emit("shader_update_vertex");
        }
	}
	
    private _useSpriteSize () {
        if(this.enabled){
            if(this._useShape){
                if (!this._spriteFrame || !this.isValid)  return;
                if (SizeMode.RAW === this._sizeMode) {
                    // @ts-ignore
                    var size = this._spriteFrame._originalSize;
					this._size = cc.size(size);
                } else if (SizeMode.TRIMMED === this._sizeMode) {
                    // @ts-ignore
					var rect = this._spriteFrame._rect;
					this._size = cc.size(rect.width, rect.height);
				}
				if(this._syncSizeToNode){
					this.node.setContentSize(this._size);
				}
				this.node.emit("shader_update_vertex");
            }
        }
    }

    private _useSpriteFrame (oldFrame:cc.SpriteFrame) {
        if(this.enabled){
            let oldTexture = oldFrame && oldFrame.getTexture();
            if (oldTexture && !oldTexture.loaded) {
                oldFrame.off('load', this._useSpriteSize, this);
            }
    
            let spriteFrame = this._spriteFrame;
            if (spriteFrame) {
				//this.node.emit("shader_update_material");
				this.onRenderUpdateMaterial();
                let newTexture = spriteFrame.getTexture();
                if (newTexture && newTexture.loaded) {
                    this._useSpriteSize();
                }
                else {
                    spriteFrame.once('load', this._useSpriteSize, this);
                }
            }
		}
		this.node.emit("shader_update_vertex");
        if (CC_EDITOR) {
            this._useAtlas(this._spriteFrame);
        }
	}

    private _useAtlas(spriteFrame:cc.SpriteFrame) {
		if(CC_EDITOR){
            //Editor.log("_useAtlas");
			// @ts-ignore
			if (spriteFrame && spriteFrame._atlasUuid) {
				var self = this;
				// @ts-ignore
				cc.assetManager.loadAny(spriteFrame._atlasUuid, function (err, asset) {
                    self._atlas = asset;
				});
			} else {
				this._atlas = null;
			}
		}
    }
}

}
